import hashlib, os
from bitbrook.utilities.chunck import ChunkFile
from threading import Lock

class Brook(object):
    def __init__(self, brookfile_path, id):
        #needed for thread stopping
        self.completed = False
        self.object_lock = Lock()
        
        self.chunk_completed = []
        self._chunk_index2hash = {}
        #this list is for any data, a given interface need to store about the chunks
        self.chunks_meta_data = []
        self.number_of_chunks = 0
        self._id = id
        self.chunk_rarety = []
        
        self._read_brook_file(brookfile_path)
        
        # if the download dir for the client does not exist, we create it
        if not os.path.exists(self._infile_dir):
            os.mkdir(self._infile_dir)
        
        #if the file does not exist it will be created and filled with zeros
        if not os.path.exists(self._infile_path):
            #build a zero chunk
            chunk = ""
            for _ in range(0, self.chunk_size):
                chunk += "0"
                
            brook = open(self._infile_path, 'w+b')            
            for _ in range (0, len(self._chunk_index2hash)-1):
                brook.write(chunk)
            brook.write(chunk[:self.last_chunk_size])
            brook.close()
        self._chunker = ChunkFile(self._infile_path, self.chunk_size)
        

    def _read_brook_file(self, brookfile_path):
        brook = open(brookfile_path)
        self.tracker = brook.readline()[10:-1]
        self._infile_dir = os.path.join(os.path.dirname(__file__), "..", "brooks", self._id)
        self._infile_path = os.path.join(self._infile_dir, brook.readline()[9:-1])
        self._brook_id = brook.readline()[11:-1]
        self.chunk_size = int(brook.readline()[13:-1])
        self.last_chunk_size = int(brook.readline()[18:-1])
        #nu er der kun liner med chunks tilbage, startende med chunk 0
        chunk_index = 0
        for line in brook:
            self.chunk_completed.append(None)
            self.chunks_meta_data.append(None)
            #self.chunk_rarety.append(0)
            self._chunk_index2hash[chunk_index] = (line[line.index("=") + 2:-1])
            chunk_index = chunk_index+1
        
        self.number_of_chunks = chunk_index-1
        brook.close()

    def verify_brook(self, network):
        for chunk_id in self._chunk_index2hash:
            if self.verify_chunk(chunk_id, self._chunker.read_chunk(chunk_id)):
                self.chunk_completed[chunk_id] = True
                if not network == None:
                    network._chunk_rarity[chunk_id] = None
            else:
                self.chunk_completed[chunk_id] = False
        for chunk in self.chunk_completed:
            if not chunk:
                self.completed = False
                print "verifying, result: ", self.completed
                return False
        self.completed = True
        print "verifying, result: ", self.completed
        return True

    def verify_chunk(self, chunk_id, chunk):
        return hashlib.sha1(chunk).hexdigest() == self._chunk_index2hash[chunk_id]
    
    def is_chunk_complete(self, chunk_id):
        return self.chunk_completed[chunk_id]
    
    def get_chunk(self, chunk_id):
        return self._chunker.read_chunk(chunk_id)
    
    #it is assumed that the chunk has been verified
    def write_chunk(self, chunk_id, chunk):
        self._chunker.write_chunk(chunk_id, chunk)
        self.chunk_completed[chunk_id] = True
        for chunk in self.chunk_completed:
            if not chunk:
                return None
        self.completed = True